﻿using System;
using System.Collections.Generic;
using System.Linq;
using Calimbra.Addin.Messages;

namespace Calimbra.Addin.Functions
{
    public class Identify_function_units
    {
        public Action<List<FunctionUnit>> Result;
        private Dictionary<string, FunctionUnit> functionUnits;
        private List<string>boards;

        public Identify_function_units()
        {
            functionUnits = new Dictionary<string, FunctionUnit>();
            boards = new List<string>();
        }
        public void Check(string row)
        {
            string[] splittedValues = row.Trim().Split(new char[]{' ','\t'});
            splittedValues = RemoveEmptyValues(splittedValues);
            if (splittedValues.Length == 0)
                return;
            if (splittedValues.Length == 1)
            {
                string boardName = splittedValues[0];
                boards.Add(boardName);
                RemoveBoard(boardName);
            }
            else if (splittedValues.Length == 2)
            {
                PrepareFunctionOutputPort(splittedValues[0]);
                PrepareFunctionInputPort(splittedValues[1]);
        
            }
            else
            {
                throw new FormatException("Format of Flow Design File is invalid!");
            }
        }

        private string[] RemoveEmptyValues(string[] splitted_values)
        {
            return splitted_values.Where(i => !string.IsNullOrWhiteSpace(i)).ToArray();
        }

        private void RemoveBoard(string boardName)
        {
          if (functionUnits.ContainsKey(boardName))
                functionUnits.Remove(boardName);
        }


        private void PrepareFunctionOutputPort(string function)
        {
            if (!function.StartsWith("."))
            {
                string[] splittedValues = function.Split('.');
                if(splittedValues.Length > 2)
                    throw new FormatException("Format of Flow Design File is invalid!");
                if (splittedValues.Length == 1 && splittedValues[0] == "in")
                    return;
                string functionName = splittedValues[0];
                string functionPort = "Result";
                if(splittedValues.Length == 2)
                    functionPort = splittedValues[1];
                
                if (functionUnits.ContainsKey(functionName))
                {
                    if (!functionUnits[functionName].OutputPortNames.Contains(functionPort))
                        functionUnits[functionName].OutputPortNames.Add(functionPort);
                }
                else
                {
                    var fu = new FunctionUnit(functionName);
                    fu.OutputPortNames.Add(functionPort);
                    functionUnits.Add(functionName, fu);
                }
            }
        }

        private void PrepareFunctionInputPort(string function)
        {
            if (!function.StartsWith("."))
            {
                string[] splittedValues = function.Split('.');
                if (splittedValues.Length > 2)
                    throw new FormatException("Format of Flow Design File is invalid!");
                if (splittedValues.Length == 1 && splittedValues[0] == "out")
                    return;
                string functionName = splittedValues[0];
                string functionPort = "Process";
                if (splittedValues.Length == 2)
                    functionPort = splittedValues[1];

                if (functionUnits.ContainsKey(functionName))
                {
                    if (!functionUnits[functionName].InputPortNames.Contains(functionPort))
                        functionUnits[functionName].InputPortNames.Add(functionPort);
                }
                else
                {
                    var fu = new FunctionUnit(functionName);
                    fu.InputPortNames.Add(functionPort);
                    functionUnits.Add(functionName, fu);
                }
            }
        }

        public void FireStatus()
        {
            Result(new List<FunctionUnit>(functionUnits.Values));
        }
    }
}